import axios, {AxiosError, AxiosHeaders, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig} from 'axios';
import {ApiResponse} from '@/entiy/vo/ApiResponse.ts';
import {BizResult} from '@/entiy/vo/BizResult.ts';
import {BizResultUtils} from '@/utils/BizResultUtils.ts';
import {useUserStore} from '@/store/UseUserStore.ts';
import router from "@/router";
import { invoke } from '@tauri-apps/api/core';

// 对 Axios 实例的基础封装，提供 GET、POST、PUT、DELETE 请求方法，
// 用于匿名接口请求，如登录、注册等不需要验证用户状态的接口场景。
export default class RequestService {

    // 静态 Axios 实例
    private static instance: AxiosInstance;

    // 静态变量存储从 Rust 获取的 baseUrl
    private static baseUrl: string | null = null;

    // 用于保证 baseUrl 只被初始化一次的 Promise
    private static baseUrlPromise: Promise<string> | null = null;

    // 初始化静态实例
    static {
        // 创建实例
        this.instance = axios.create({
            // 请求超时时间
            timeout: 30000,

            // 请求头
            headers: {
                'Content-Type': 'application/json',
            },

            // 跨域
            withCredentials: true,
        });

        // 添加请求拦截器
        this.instance.interceptors.request.use(
            this.handleRequest,
            this.handleRequestError
        );

        // 添加响应拦截器
        this.instance.interceptors.response.use(
            this.handleResponse,
            this.handleResponseError
        );
    }

    /**
     * 初始化 baseUrl 的方法，确保只从 Rust 获取一次 URL
     */
    private static async initializeBaseUrl(): Promise<string> {
        // 如果已经有 Promise 在进行中，直接返回该 Promise
        if (this.baseUrlPromise) {
            return this.baseUrlPromise;
        }

        // 创建新的 Promise 并保存
        this.baseUrlPromise = (async () => {
            try {
                // 如果 baseUrl 已经存在，直接返回
                if (this.baseUrl) {
                    return this.baseUrl;
                }

                // 从 Rust 获取 URL
                const url = await invoke("get_url") as string;
                this.baseUrl = url;
                return url;
            } catch (error) {
                console.error('获取 baseUrl 失败:', error);
                // 返回默认 URL 作为备选
                return '';
            }
        })();

        return this.baseUrlPromise;
    }

    /**
     * 请求成功拦截器处理方法
     * 在请求发送前添加 token 到请求头
     *
     * @param config Axios 请求配置
     * @returns 处理后的请求配置
     */
    private static handleRequest(config: InternalAxiosRequestConfig): InternalAxiosRequestConfig {
        config.headers = config.headers || {};
        config.headers.token = useUserStore().token;
        return config;
    }

    /**
     * 请求失败拦截器处理方法
     *
     * @param error 请求错误对象
     * @returns 拒绝的 Promise
     */
    private static handleRequestError(error: AxiosError): Promise<AxiosError> {
        return Promise.reject(error);
    }

    /**
     * 响应数据处理拦截器
     *
     * @param response 响应数据
     * @return 处理后的响应数据
     */
    private static handleResponse(response: AxiosResponse): Promise<any> {
        if (response.status === 200) {
            // 用户登录过期处理
            if (response.data.code === -10000 && response.config.url !== '/logout') {
                useUserStore().logout().finally(() => {
                    router.push('/auth/login').then();
                });
            }

            return Promise.resolve(response.data);
        } else {
            return Promise.reject('系统繁忙, 请稍后再试');
        }
    }

    /**
     * 请求错误处理拦截器
     *
     * @param error 错误
     * @return 处理后的结果
     */
    private static handleResponseError(error: AxiosError): Promise<never> {
        return Promise.reject(error);
    }

    /**
     * 通用的请求处理方法
     *
     * @param url    请求的URL
     * @param config 请求参数（可选）
     * @returns 返回处理后的响应数据或错误
     */
    public static async get<T>(url: string, config?: any): Promise<BizResult<T>> {
        try {
            const baseUrl = await this.initializeBaseUrl();
            const fullUrl = baseUrl + url;
            const response: AxiosResponse<ApiResponse<T>> = await this.instance.get<ApiResponse<T>>(fullUrl, config);
            return BizResultUtils.handleResult(response);
        } catch (e) {
            console.log('接口调用失败:', e);
            return BizResultUtils.systemError();
        }
    }

    /**
     * 通用的请求处理方法
     *
     * @param url  请求的URL
     * @param data 请求参数（可选）
     * @returns 返回处理后的响应数据或错误
     */
    public static async post<T>(url: string, data?: any): Promise<BizResult<T>> {
        try {
            const baseUrl = await this.initializeBaseUrl();
            const fullUrl = baseUrl + url;
            const response: AxiosResponse<ApiResponse<T>> = await this.instance.post<ApiResponse<T>>(fullUrl, data);
            return BizResultUtils.handleResult(response);
        } catch (e) {
            console.log('接口调用失败:', e);
            return BizResultUtils.systemError();
        }
    }

    /**
     * 通用的上传文件请求处理方法
     *
     * @param url  请求的 URL
     * @param data 请求参数（可选）
     * @returns 返回处理后的响应数据或错误
     */
    public static async updateFile<T>(url: string, data: FormData): Promise<BizResult<T>> {
        try {
            const baseUrl = await this.initializeBaseUrl();
            const fullUrl = baseUrl + url;
            const response = await this.instance.post<ApiResponse<T>>(fullUrl, data, {
                headers: new AxiosHeaders({
                    'Content-Type': 'multipart/form-data'
                }),
            });
            return BizResultUtils.handleResult(response);
        } catch (e) {
            // console.log("接口调用失败:", e);
            return BizResultUtils.systemError();
        }
    }
}
